﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "StructureInstanceUtils.h"
#include "AlgorithmMinimalDistance.h"
#include "AlgorithmProperty.h"
#include "GbmpBuiltInParameterDefinitionsNew.h"
#include "GbmpBuiltInParameterStaticVauleListItems.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "GraphicsNodeUtils.h"
#include "IArc2d.h"
#include "IArc3d.h"
#include "IBaseGraphicsElementShapeComponent.h"
#include "IDocument.h"
#include "IElementModelShape.h"
#include "IElementParameters.h"
#include "IElementPosition.h"
#include "IElementPositionPoints.h"
#include "IFace.h"
#include "IFamily.h"
#include "IGraphicsBRepBody.h"
#include "IGraphicsBRepFace.h"
#include "IGraphicsElementShape.h"
#include "IInstance.h"
#include "IInstanceType.h"
#include "ILine2d.h"
#include "ILine3d.h"
#include "IOpeningGraphicsElementShapeComponent.h"
#include "IParameter.h"
#include "IParameterDefinitionLibrary.h"
#include "IParameterValueCurveByPoints.h"
#include "IPlane.h"
#include "IPolygon.h"
#include "IPositionCurve2d.h"
#include "IPositionSingleAssociatedPlaneWithTwoOffsets.h"
#include "IStructureFloor.h"
#include "ITrimmedSurface.h"
#include "LevelUtils.h"
#include "LineFamilyPositionCurveSideType.h"
#include "MathUtils.h"
#include "UniIdentity.h"
#include "Vector3dUtils.h"
#include "IGeometryRelationshipComponent.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace std;

bool StructureInstanceUtils::SetInstanceOutputParamValueByParamUid(IInstance *pInstance, double value,const UniIdentity &paramDefUid)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    IDocument *pDoc = pInstance->GetDocument();
    DBG_WARN_AND_RETURN_UNLESS(pDoc, false, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    //OwnerPtr<IParameter> pParam = NEW_AS_OWNER_PTR(Parameter, pDoc, ParameterStorageType::Double, 
        //false, false, true, paramDefUid, ParameterProcessType::GeneralOutput);
    ParameterAttributes pa = {false, false, true};
    OwnerPtr<IParameter> pParam= IParameter::CreateParameter(pDoc, ParameterStorageType::Double, pa, 
        paramDefUid, ParameterProcessType::GeneralOutput);
    pParam->SetValueAsDouble(value);

    IElementParameters *pParamBehavior = pInstance->GetElementParameters();
    DBG_WARN_AND_RETURN_UNLESS(pParamBehavior, false, L"ParamBehavior为空",L"GDMPLab",L"2024-03-30");

    std::wstring errorMsg;
    //bool bOK= pParamBehavior->SetParameter(Parameter(pDoc, pParam.get()), &errorMsg);
    bool bOK= pParamBehavior->SetParameter(pParam.get(), &errorMsg);
    DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"预期Parameter不存在",L"GDMPLab",L"2024-03-30");

    return true;
}


double gcmp::StructureInstanceUtils::GetInstanceVolume(const IInstance *pInstance)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, 0, L"构件为空",L"GDMPLab",L"2024-03-30");

    // 获取形体
    const IElementModelShape *pGrepBehavior = pInstance->GetElementModelShape();
    DBG_WARN_AND_RETURN_UNLESS(pGrepBehavior, 0, L"构件GraphicsElementShapeBehavior为空",L"GDMPLab",L"2024-03-30");
    const IGraphicsElementShape *pGrep = pGrepBehavior->GetGraphicsElementShape();
    if (!pGrep)
    {
        return 0;
    }

    // 获取几何Body
    std::vector<const IGraphicsBRepBody*> instanceBodies;
    std::vector<Matrix4d> instanceTransforms;
    GraphicsNodeUtils::CollectBRepBodies(pInstance->GetDocument(), pGrep, &instanceBodies, &instanceTransforms);

    // 计算体积
    double volume = 0;
    FOR_EACH(pBody, instanceBodies)
    {
        volume += AlgorithmProperty::GetVolume(pBody->GetGeometry());
    }
    return volume;
}

gcmp::GraphicsNodeId gcmp::StructureInstanceUtils::GetInstanceSideFaceId(IInstance* pInstance)
{
    GraphicsNodeId returnValue;
    DBG_WARN_AND_RETURN_UNLESS(pInstance, returnValue, L"构件为空",L"GDMPLab",L"2024-03-30");

    // 获取定位线，用以区分直线/弧形构件
    const IElementPosition *pPosBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_UNLESS(pPosBehavior, returnValue, L"定位对象为空",L"GDMPLab",L"2024-03-30");
    const IPositionGeometry *pPosition = pPosBehavior->GetPositionGeometry();
    DBG_WARN_AND_RETURN_UNLESS(pPosition, returnValue, L"定位对象为空",L"GDMPLab",L"2024-03-30");
    const IPositionCurve2d *pPosCurve2d = quick_cast<IPositionCurve2d>(pPosition);
    DBG_WARN_AND_RETURN_UNLESS(pPosCurve2d, returnValue, L"不是线式族不应该到执行到这里",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IParameter> sideFaceParam;
    const IArc2d *pArc2d = quick_cast<IArc2d>(pPosCurve2d->GetBaseCurve());
    const IType *pType = pInstance->GetBasicInformation()->GetType();
    DBG_WARN_AND_RETURN_UNLESS(pType, returnValue, L"构件Type为空",L"GDMPLab",L"2024-03-30");
    if (pArc2d && !pArc2d->IsAntiClockwise())  // 如果是顺时针圆弧，内（左）侧面半径较大，取内（左）侧面
    {
        if (pType->GetElementParameters())
            sideFaceParam = pType->GetElementParameters()->GetParameterByUid(PARAMETER_UID(InteriorFaceNodeTagBuiltInParameter));
    }
    else  // 默认取外（右）侧面
    {
        if (pType->GetElementParameters())
            sideFaceParam = pType->GetElementParameters()->GetParameterByUid(PARAMETER_UID(ExteriorFaceNodeTagBuiltInParameter));
    }
    DBG_WARN_AND_RETURN_UNLESS(IParameter::IsValidParameter(sideFaceParam), returnValue, L"构件侧面的参数不存在",L"GDMPLab",L"2024-03-30");
    returnValue = GraphicsNodeId(sideFaceParam->GetValueAsInt());


    return returnValue;
}

bool StructureInstanceUtils::GetInstanceLength(const IInstance* pInstance, double& length)
{
    std::vector<Vector3d> controlPts = GetInstanceControlPoints(pInstance);
    if (controlPts.size() == 2)
    {
        length = Vector3d(controlPts[1] - controlPts[0]).Length();

        return true;
    }
    else
    {
        // 圆弧暂不支持倾斜
        bool bOk = GetInstanceHorizontalLength(pInstance, length);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"GetInstanceHorizontalLength失败",L"GDMPLab",L"2024-03-30");

        return true;
    }
}

bool StructureInstanceUtils::GetInstanceHorizontalLength(const IInstance* pInstance, double& length)
{
    // 获取水平定位线
    const IElementPosition* pPosBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPosBehavior, L"pPosBehavior为空",L"GDMPLab",L"2024-03-30");
    const IPositionGeometry* pPosition = pPosBehavior->GetPositionGeometry();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPosition, L"pPosition2d为空",L"GDMPLab",L"2024-03-30");
    const IPositionGeometry* pPosCurve2d = quick_cast<IPositionGeometry>(pPosition);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPosCurve2d, L"pPosCurve2d为空",L"GDMPLab",L"2024-03-30");

    // 定位线长度
    const ICurve* pCurve = dynamic_cast<const ICurve*>(pPosCurve2d->GetGeometry());
    length = pCurve->GetLength();

    return true;
}

bool StructureInstanceUtils::GetInstanceFamilyTypeParamValueByParamUid(const IInstance *pInstance, double &value,const UniIdentity &paramDefUid)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    const IType *pFamilyType = pInstance->GetBasicInformation()->GetType();
    DBG_WARN_AND_RETURN_UNLESS(pFamilyType, false, L"构件类型为空",L"GDMPLab",L"2024-03-30");
    const IElementParameters *pParamBehavior = pFamilyType->GetElementParameters();
    DBG_WARN_AND_RETURN_UNLESS(pParamBehavior, false, L"ParamBehavior为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IParameter> param = pParamBehavior->GetParameterByUid(paramDefUid);
    if (IParameter::IsValidParameter(param))
    {
        value = param->GetValueAsDouble();
        return true;
    }
    return false;
}

std::vector<IGraphicsBRepFace*> gcmp::StructureInstanceUtils::GetFloorTopBottomFaces(IGraphicsBRepBody* pBody)
{
    std::vector<IGraphicsBRepFace*> startEndFaces;
    DBG_WARN_AND_RETURN_UNLESS(pBody, startEndFaces, L"pBody为空",L"GDMPLab",L"2024-03-30");

    IGraphicsBRepFace* pTopFace = nullptr;
    IGraphicsBRepFace* pBottomFace = nullptr;

    int faceCount = pBody->GetFaceCount();
    for (int i = 0; i < faceCount; ++i)
    {
        IGraphicsBRepFace* pBRepFace = pBody->GetFaceFW(i);
        DBG_WARN_AND_CONTINUE_UNLESS(pBRepFace, L"pBRepFace为空",L"GDMPLab",L"2024-03-30");
        if (!pBRepFace->IsPlanar())
            continue;
        if (Vector3dUtils::IsPerpendicular(pBRepFace->GetNormal(), Vector3d::UnitZ))
        {
            continue;
        }
        if (MathUtils::IsGreaterThan(pBRepFace->GetNormal().Dot(Vector3d::UnitZ), 0.0, Constants::LENGTH_EPS))
        {
            pTopFace = pBRepFace;
        }
        else
        {
            pBottomFace = pBRepFace;
        }
    }
    DBG_WARN_AND_RETURN_UNLESS(pTopFace, startEndFaces, L"pTopFace为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_UNLESS(pBottomFace, startEndFaces, L"pBottomFace为空",L"GDMPLab",L"2024-03-30");

    startEndFaces.push_back(pTopFace);
    startEndFaces.push_back(pBottomFace);
    return startEndFaces;
}

bool StructureInstanceUtils::GetFloorTopArea(const IInstance *pInstance, double &value)
{
    // 获取GRep
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    const IElementModelShape *pGrepBehavior = pInstance->GetElementModelShape();
    DBG_WARN_AND_RETURN_UNLESS(pGrepBehavior, false, L"构件GraphicsElementShapeBehavior为空",L"GDMPLab",L"2024-03-30");
    const IGraphicsElementShape *pGrep = pGrepBehavior->GetGraphicsElementShape();
    DBG_WARN_AND_RETURN_UNLESS(pGrep, false, L"构件Grep为空",L"GDMPLab",L"2024-03-30");

    // 获取几何Body
    std::vector<const IGraphicsBRepBody*> instanceBodies;
    std::vector<Matrix4d> instanceTransforms;
    GraphicsNodeUtils::CollectBRepBodies(pInstance->GetDocument(), pGrep, &instanceBodies, &instanceTransforms);
    DBG_WARN_AND_RETURN_UNLESS(instanceBodies.size() == 1 && instanceBodies.size() == 1, false, L"Body应该只有一个",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IGraphicsBRepBody> opBody = TransferOwnershipCast<IGraphicsBRepBody>(instanceBodies.front()->Clone());
    DBG_WARN_AND_RETURN_UNLESS(opBody.get(), false, L"opBody为空",L"GDMPLab",L"2024-03-30");
    std::vector<IGraphicsBRepFace*> vecTopBottomFace = GetFloorTopBottomFaces(opBody.get());
    if (!vecTopBottomFace.empty())
    {
        value = AlgorithmProperty::GetArea(vecTopBottomFace.front()->GetGmFace());
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetFloorTopElevation(const IInstance *pInstance, double &value)
{
    //注：非水平时不能返回false，因为非水平时计算坡度线起终点高度也需要计算顶部高程
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    double levelValue = 0;
    double topOffset = 0;
    if (GetInstanceAssociatedLevelValue(pInstance, levelValue) && GetInstanceTopOffset(pInstance, topOffset))
    {
        value = levelValue + topOffset;
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetFloorBottomElevation(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    double topElevation = 0;
    double thickness = 0;
    if (GetFloorTopElevation(pInstance, topElevation)&&GetFloorCoreThickness(pInstance,thickness))
    {
        value = topElevation - thickness;
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetFloorCoreThickness(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    UniIdentity coreThicknessParamUid = PARAMETER_UID(FloorCoreThicknessBuiltInParameter);
    bool bOK = GetInstanceFamilyTypeParamValueByParamUid(pInstance, value, coreThicknessParamUid);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOK, L"floorCoreThickness为空",L"GDMPLab",L"2024-03-30");
    return true;
}

bool StructureInstanceUtils::GetFloorSlopeAngle(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    const IElement *pSlopeLine = GetFloorSlopeLine(pInstance);
    if (pSlopeLine)
    {
        UniIdentity slopeAngleParamUid = PARAMETER_UID(FloorSlopeAngleValueBuiltInParameter);
        OwnerPtr<IParameter> slopeAngleParam = pSlopeLine->GetElementParameters()->GetParameterByUid(slopeAngleParamUid);
        DBG_WARN_AND_RETURN_UNLESS(IParameter::IsValidParameter(slopeAngleParam), false, L"坡度线的角度参数为空",L"GDMPLab",L"2024-03-30");
        value = slopeAngleParam->GetValueAsDouble();
    }
    else
    {
        value = 0;
    }
    return true;
}

bool StructureInstanceUtils::GetFloorSlopeStartEndHeight(const IInstance *pInstance, double &start, double &end)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    const IElement *pSlopeLine = GetFloorSlopeLine(pInstance);
    double topElevation = 0;
    bool bTopElevationExist = GetFloorTopElevation(pInstance, topElevation);
    DBG_WARN_AND_RETURN_UNLESS(bTopElevationExist, false, L"顶部高程不存在",L"GDMPLab",L"2024-03-30");
    if (pSlopeLine)
    {
        UniIdentity slopeStartOffsetParamUid = PARAMETER_UID(FloorSlopeStartOffsetBuiltInParameter);
        UniIdentity slopeEndOffsetParamUid = PARAMETER_UID(FloorSlopeEndOffsetBuiltInParameter);
        OwnerPtr<IParameter> slopeStartOffsetParam = pSlopeLine->GetElementParameters()->GetParameterByUid(slopeStartOffsetParamUid);
        OwnerPtr<IParameter> slopeEndOffsetParam = pSlopeLine->GetElementParameters()->GetParameterByUid(slopeEndOffsetParamUid);
        DBG_WARN_AND_RETURN_UNLESS(IParameter::IsValidParameter(slopeStartOffsetParam), false, L"为空",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_UNLESS(IParameter::IsValidParameter(slopeEndOffsetParam), false, L"为空",L"GDMPLab",L"2024-03-30");
        start = topElevation + slopeStartOffsetParam->GetValueAsDouble();
        end = topElevation + slopeEndOffsetParam->GetValueAsDouble();
    }
    else
    {
        start = topElevation;
        end = topElevation;
    }
    return true;
}

const IElement* gcmp::StructureInstanceUtils::GetFloorSlopeLine(const IInstance *pInstance)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"构件为空",L"GDMPLab",L"2024-03-30");
    IDocument *pDoc = pInstance->GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"文档为空",L"GDMPLab",L"2024-03-30");

    const IStructureFloor* pStructureFloor = IStructureFloor::Get(pInstance);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStructureFloor, L"ExternalData为空",L"GDMPLab",L"2024-03-30");

    ElementId slopeId = pStructureFloor->GetSlopeLineId();
    IElement *pSlopeLine = slopeId.IsValid() ? pDoc->GetElement(slopeId) : nullptr;
    return pSlopeLine;
}

bool gcmp::StructureInstanceUtils::GetRaftFoundationZPositioningType(const IInstance *pInstance, RaftFoundationZPositioningType &type)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IParameter> ZPositionParam = pInstance->GetElementParameters()->GetParameterByUid(PARAMETER_UID(RaftFoundationZPositioningTypeBuiltInParameter));
    DBG_WARN_AND_RETURN_UNLESS(IParameter::IsValidParameter(ZPositionParam), false, L"没有定位线位置参数",L"GDMPLab",L"2024-03-30");
    type = (RaftFoundationZPositioningType)ZPositionParam->GetValueAsInt();
    return true;
}

bool gcmp::StructureInstanceUtils::GetRaftFoundationThickness(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    UniIdentity thicknessParamUid = PARAMETER_UID(RaftFoundationThicknessBuiltInParameter);
    bool bOK = GetInstanceFamilyTypeParamValueByParamUid(pInstance, value, thicknessParamUid);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOK, L"raftFoundationThickness为空",L"GDMPLab",L"2024-03-30");
    return true;

}

bool StructureInstanceUtils::GetRaftFoundationBottomArea(const IInstance *pInstance, double &value)
{
    // 获取GRep
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    const IElementModelShape *pGrepBehavior = pInstance->GetElementModelShape();
    DBG_WARN_AND_RETURN_UNLESS(pGrepBehavior, false, L"构件GraphicsElementShapeBehavior为空",L"GDMPLab",L"2024-03-30");
    const IGraphicsElementShape *pGrep = pGrepBehavior->GetGraphicsElementShape();
    DBG_WARN_AND_RETURN_UNLESS(pGrep, false, L"构件Grep为空",L"GDMPLab",L"2024-03-30");

    // 获取几何Body
    std::vector<const IGraphicsBRepBody*> instanceBodies;
    std::vector<Matrix4d> instanceTransforms;
    GraphicsNodeUtils::CollectBRepBodies(pInstance->GetDocument(), pGrep, &instanceBodies, &instanceTransforms);
    DBG_WARN_AND_RETURN_UNLESS(instanceBodies.size() == 1 && instanceBodies.size() == 1, false, L"Body应该只有一个",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IGraphicsBRepBody> opBody = TransferOwnershipCast<IGraphicsBRepBody>(instanceBodies.front()->Clone());
    DBG_WARN_AND_RETURN_UNLESS(opBody.get(), false, L"opBody为空",L"GDMPLab",L"2024-03-30");

    //获取下表面
    IGraphicsBRepFace* pBottomFace = nullptr;
    int faceCount = opBody->GetFaceCount();
    for (int i = 0; i < faceCount; ++i)
    {
        IGraphicsBRepFace* pBRepFace = opBody->GetFaceFW(i);
        DBG_WARN_AND_CONTINUE_UNLESS(pBRepFace, L"pBRepFace为空",L"GDMPLab",L"2024-03-30");
        if (!pBRepFace->IsPlanar())
            continue;
        if (Vector3dUtils::IsParallel(pBRepFace->GetNormal(), Vector3d::UnitZ))
        {
            if (MathUtils::IsLessThan(pBRepFace->GetNormal().Dot(Vector3d::UnitZ), 0.0, Constants::LENGTH_EPS))
            {
                pBottomFace = pBRepFace;
                break;
            }
        }
    }
    DBG_WARN_AND_RETURN_UNLESS(pBottomFace, false, L"pBottomFace为空",L"GDMPLab",L"2024-03-30");
    value = AlgorithmProperty::GetArea(pBottomFace->GetGmFace());
    return true;
}

bool StructureInstanceUtils::GetRaftFoundationTopElevation(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    double levelValue = 0;
    double topOffset = 0;
    double thickness = 0;
    RaftFoundationZPositioningType Ztype;

    if (GetInstanceAssociatedLevelValue(pInstance, levelValue) &&
        GetInstanceTopOffset(pInstance, topOffset)&&
        GetRaftFoundationThickness(pInstance, thickness)&&
        GetRaftFoundationZPositioningType(pInstance, Ztype))
    {
        if (RaftFoundationZPositioningType::Top == Ztype)
        {
            value = levelValue + topOffset;
            return true;
        }
        else if (RaftFoundationZPositioningType::Bottom == Ztype)
        {
            value = levelValue + topOffset + thickness;
            return true;
        }
    }
    return false;
}

bool StructureInstanceUtils::GetRaftFoundationBottomElevation(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    double topElevation = 0;
    double thickness = 0;
    if (GetRaftFoundationTopElevation(pInstance, topElevation)&&
        GetRaftFoundationThickness(pInstance, thickness))
    {
        value = topElevation - thickness;
        return true;
    }
    return false;
}

std::vector<Vector3d> StructureInstanceUtils::GetInstanceControlPoints(const IInstance* pInstance)
{
    std::vector<Vector3d> controlPts;
    DBG_WARN_AND_RETURN_UNLESS(pInstance, controlPts, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    const IElementPositionPoints* pCtrlPtBehavior = pInstance->GetPositionPoints();
    DBG_WARN_AND_RETURN_UNLESS(pCtrlPtBehavior, controlPts, L"pCtrlPtBehavior为空",L"GDMPLab",L"2024-03-30");

    int ptCount = pCtrlPtBehavior->GetControlPointCount();
    if (ptCount == 2)
    {
        controlPts.push_back(pCtrlPtBehavior->GetControlPoint(0));
        controlPts.push_back(pCtrlPtBehavior->GetControlPoint(1));
    }
    else if (ptCount == 3)
    {
        controlPts.push_back(pCtrlPtBehavior->GetControlPoint(0));
        controlPts.push_back(pCtrlPtBehavior->GetControlPoint(1));
        controlPts.push_back(pCtrlPtBehavior->GetControlPoint(2));
    }
    else
    {
        DBG_WARN_AND_RETURN_UNLESS(false, controlPts, L"不支持的控制点类型",L"GDMPLab",L"2024-03-30");
    }

    return controlPts;
}

std::vector<IGraphicsBRepFace*> StructureInstanceUtils::GetBasicBeamStartEndFaces(IGraphicsBRepBody* pBody, const Vector3d& startPos, const Vector3d& endPos)
{
    std::vector<IGraphicsBRepFace*> startEndFaces;
    DBG_WARN_AND_RETURN_UNLESS(pBody, startEndFaces, L"pBody为空",L"GDMPLab",L"2024-03-30");
    Vector3d posDir(endPos - startPos);

    IGraphicsBRepFace* pStartFace = nullptr;
    IGraphicsBRepFace* pEndFace = nullptr;

    int faceCount = pBody->GetFaceCount();
    for (int i = 0; i < faceCount; ++i)
    {
        IGraphicsBRepFace* pBRepFace = pBody->GetFaceFW(i);
        DBG_WARN_AND_CONTINUE_UNLESS(pBRepFace, L"pBRepFace为空",L"GDMPLab",L"2024-03-30");
        if (!pBRepFace->IsPlanar())
            continue;

        if (Vector3dUtils::IsParallel(pBRepFace->GetNormal(), posDir))
        {
            IFace* pFace = pBRepFace->GetGmFaceFW();
            DBG_WARN_AND_CONTINUE_UNLESS(pFace, L"pFace为空",L"GDMPLab",L"2024-03-30");

            Vector3d minimalDistancePointOnSurface;
            double distanceStartPos(0);
            bool bOk = AlgorithmMinimalDistance::Calculate(pFace->GetTrimmedSurface(), startPos, minimalDistancePointOnSurface, false, nullptr, distanceStartPos);
            DBG_WARN_AND_CONTINUE_UNLESS(bOk, L"距离计算失败",L"GDMPLab",L"2024-03-30");
            double distanceEndPos(0);
            bOk = AlgorithmMinimalDistance::Calculate(pFace->GetTrimmedSurface(), endPos, minimalDistancePointOnSurface, false, nullptr, distanceEndPos);
            DBG_WARN_AND_CONTINUE_UNLESS(bOk, L"距离计算失败",L"GDMPLab",L"2024-03-30");

            if (MathUtils::IsLessThan(distanceStartPos, distanceEndPos, Constants::LENGTH_EPS))
            {
                pStartFace = pBRepFace;
            }
            else
            {
                pEndFace = pBRepFace;
            }
        }
    }
    DBG_WARN_AND_RETURN_UNLESS(pStartFace, startEndFaces, L"pStartFace为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_UNLESS(pEndFace, startEndFaces, L"pEndFace为空",L"GDMPLab",L"2024-03-30");

    startEndFaces.push_back(pStartFace);
    startEndFaces.push_back(pEndFace);
    return startEndFaces;
}

std::vector<OwnerPtr<IPlane>> StructureInstanceUtils::GetBasicBeamStartEndSectionPlanes(const Vector3d& startPos, const Vector3d& endPos, InstanceEndType sectionType)
{
    std::vector<OwnerPtr<IPlane>> sectionPlanes;

    if (sectionType == InstanceEndType::Vertical)
    {
        Vector3d direction(endPos - startPos);
        direction.SetZ(0);
        direction.Normalize();

        sectionPlanes.push_back(IPlane::Create(startPos, direction));
        sectionPlanes.push_back(IPlane::Create(endPos, direction));
    }
    else
    {
        DBG_WARN(L"尚不支持该端面类型",L"GDMPLab",L"2024-03-30");
    }

    return sectionPlanes;
}

bool StructureInstanceUtils::GetBeamThickness(IDocument* pDoc, const ElementId& instanceTypeId, double& thickness)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    const IInstanceType* pInstanceType = quick_cast<const IInstanceType>(pDoc->GetElement(instanceTypeId));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");

    const IElementParameters* pParameterBehavior = pInstanceType->GetElementParameters();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pParameterBehavior, L"pParameterBehavior为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IParameter> paramThickness = pParameterBehavior->GetParameterByUid(PARAMETER_UID(RectSectionWidthBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(IParameter::IsValidParameter(paramThickness), L"paramThickness无效",L"GDMPLab",L"2024-03-30");

    thickness = paramThickness->GetValueAsDouble();
    return true;
}

bool StructureInstanceUtils::GetBeamThickness(const IInstance* pInstance, double& thickness)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstance, L"构件为空",L"GDMPLab",L"2024-03-30");
    UniIdentity rectSectionWidthParamUid = PARAMETER_UID(RectSectionWidthBuiltInParameter);
    bool bOK = GetInstanceFamilyTypeParamValueByParamUid(pInstance, thickness, rectSectionWidthParamUid);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOK, L"beamThickness为空",L"GDMPLab",L"2024-03-30");
    return true;
}

std::vector<Vector3d> StructureInstanceUtils::GetPositioningPoints(const std::vector<Vector3d>& basePts, double thickness, LineFamilyPositionCurveSideType yPositioningType)
{
    if (yPositioningType == LineFamilyPositionCurveSideType::CenterLineFamilyPositionCurveSideType)
        return basePts;

    std::vector<Vector3d> adjustedStartEndPts;
    double offset = thickness / 2;
    Vector3d workplaneNormal = Vector3d::UnitZ;

    if (basePts.size() == 2)
    {
        Vector3d startPt = basePts[0];
        Vector3d endPt = basePts[1];
        Vector3d tangent = endPt - startPt;
        Vector3d moveDir;
        if (yPositioningType == LineFamilyPositionCurveSideType::LeftLineFamilyPositionCurveSideType)
        {
            moveDir = tangent.Cross(workplaneNormal);
        }
        else
        {
            moveDir = workplaneNormal.Cross(tangent);
        }
        moveDir.Normalize();

        adjustedStartEndPts.push_back(startPt + moveDir * offset);
        adjustedStartEndPts.push_back(endPt + moveDir * offset);
    }
    else if (basePts.size() == 3)
    {
        OwnerPtr<IArc3d> opArc = IArc3d::Create(basePts[0], basePts[1], basePts[2]);
        FOR_EACH(pt, basePts)
        {
            double ptParam = 0;
            bool isInRange = false;
            bool bOk = opArc->GetParameter(pt, ptParam, isInRange, Constants::LENGTH_EPS);
            DBG_WARN_AND_CONTINUE_UNLESS(bOk, L"GetParameter失败",L"GDMPLab",L"2024-03-30");

            Vector3d tangent = opArc->GetTangent(ptParam);
            Vector3d moveDir;
            if (yPositioningType == LineFamilyPositionCurveSideType::LeftLineFamilyPositionCurveSideType)
            {
                moveDir = tangent.Cross(workplaneNormal);
            }
            else
            {
                moveDir = workplaneNormal.Cross(tangent);
            }
            moveDir.Normalize();

            adjustedStartEndPts.push_back(pt + moveDir * offset);
        }
    }
    else
    {
        DBG_WARN(L"不支持的类型",L"GDMPLab",L"2024-03-30");
    }

    return adjustedStartEndPts;
}

std::vector<Vector3d> StructureInstanceUtils::GetPointsByOffset(const std::vector<Vector3d>& basePts, double offset)
{
    if (MathUtils::IsZero(offset, Constants::LENGTH_EPS))
        return basePts;

    std::vector<Vector3d> adjustedPts;
    if (basePts.size() == 2)
    {
        Vector3d startPt = basePts[0];
        Vector3d endPt = basePts[1];
        Vector3d tangent = endPt - startPt;
        Vector3d workplaneNormal = Vector3d::UnitZ;
        Vector3d moveDir = tangent.Cross(workplaneNormal);
        moveDir.Normalize();

        adjustedPts.push_back(startPt + moveDir * offset);
        adjustedPts.push_back(endPt + moveDir * offset);
    }
    else if (basePts.size() == 3)
    {
        OwnerPtr<IArc3d> opArc = IArc3d::Create(basePts[0], basePts[1], basePts[2]);
        double radius = opArc->GetRadius();
        double newRadius = radius + offset;
        if (MathUtils::IsLessThan(newRadius, 0.0, Constants::LENGTH_EPS))
            return basePts;
        opArc->SetRadius(newRadius);

        adjustedPts.push_back(opArc->GetStartPoint());
        adjustedPts.push_back(opArc->GetEndPoint());
        adjustedPts.push_back(opArc->GetMiddlePoint());
    }
    else
    {
        DBG_WARN(L"不支持的类型",L"GDMPLab",L"2024-03-30");
    }
    return adjustedPts;
}

bool StructureInstanceUtils::GetBasicBeamTopElevation(const IInstance *pInstance, double &value)
{
    //注：弧形基本梁与直线基本梁合成一个族，其中弧形基本梁无起终点偏移参数，有（顶部）标高偏移，直线基本梁两者均有
    double levelOffset = 0;
    bool bLevelOffsetExist = GetInstanceTopOffset(pInstance, levelOffset);
    DBG_WARN_AND_RETURN_UNLESS(bLevelOffsetExist, false, L"无标高偏移",L"GDMPLab",L"2024-03-30");

    double startOffset = 0;
    double endOffset = 0;
    bool bStartEndOffsetExist = GetInstanceStartEndOffset(pInstance, startOffset, endOffset);

    if (!bStartEndOffsetExist ||
        (bStartEndOffsetExist&&MathUtils::IsEqual(startOffset - endOffset, 0, Constants::LENGTH_EPS)))
    {
        BeamZPositioningType ZPositionType;
        double positionLevel = 0;
        double sectionHeight = 0;
        if (GetBeamZPositionLineType(pInstance, ZPositionType) &&
            GetInstanceAssociatedLevelValue(pInstance, positionLevel) &&
            GetBasicBeamSectionHeight(pInstance, sectionHeight))
        {
            double startEndOffset = bStartEndOffsetExist ? startOffset : 0;
            if (ZPositionType == BeamZPositioningType::Top)
            {
                value = positionLevel + levelOffset + startEndOffset;
            }
            else if (ZPositionType == BeamZPositioningType::Bottom)
            {
                value = positionLevel + levelOffset + startEndOffset + sectionHeight;
            }
            return true;
        }
    }
    return false;
}

bool StructureInstanceUtils::GetBasicBeamBottomElevation(const IInstance *pInstance, double &value)
{
    double levelOffset = 0;
    bool bLevelOffsetExist = GetInstanceTopOffset(pInstance, levelOffset);
    DBG_WARN_AND_RETURN_UNLESS(bLevelOffsetExist, false, L"无标高偏移",L"GDMPLab",L"2024-03-30");

    double startOffset = 0;
    double endOffset = 0;
    bool bStartEndOffsetExist = GetInstanceStartEndOffset(pInstance, startOffset, endOffset);

    if (!bStartEndOffsetExist ||
        (bStartEndOffsetExist&&MathUtils::IsEqual(startOffset - endOffset, 0, Constants::LENGTH_EPS)))
    {
        BeamZPositioningType ZPositionType;
        double positionLevel = 0;
        double sectionHeight = 0;
        if (GetBeamZPositionLineType(pInstance, ZPositionType) &&
            GetInstanceAssociatedLevelValue(pInstance, positionLevel) &&
            GetBasicBeamSectionHeight(pInstance, sectionHeight))
        {
            double startEndOffset = bStartEndOffsetExist ? startOffset : 0;
            if (ZPositionType == BeamZPositioningType::Top)
            {
                value = positionLevel + levelOffset + startEndOffset-sectionHeight;
            }
            else if (ZPositionType == BeamZPositioningType::Bottom)
            {
                value = positionLevel + levelOffset + startEndOffset;
            }
            return true;
        }
    }
    return false;
}

bool StructureInstanceUtils::GetBasicBeamStartTopElevation(const IInstance *pInstance, double &value)
{
    double startOffset = 0;
    double endOffset = 0;
    double levelOffset = 0;
    bool bStartEndOffsetExist = GetInstanceStartEndOffset(pInstance, startOffset, endOffset);
    bool bLevelOffsetExist = GetInstanceTopOffset(pInstance, levelOffset);

    if (bStartEndOffsetExist && 
        bLevelOffsetExist &&
        !MathUtils::IsEqual(startOffset - endOffset, 0, Constants::LENGTH_EPS))
    {
        BeamZPositioningType ZPositionType;
        double positionLevel = 0;
        double sectionHeight = 0;
        double beamLength = 0;

        bool bOK = GetBeamZPositionLineType(pInstance, ZPositionType);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有定位线位置参数",L"GDMPLab",L"2024-03-30");
        bOK = GetInstanceAssociatedLevelValue(pInstance, positionLevel);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有关联标高参数",L"GDMPLab",L"2024-03-30");
        bOK = GetBasicBeamSectionHeight(pInstance, sectionHeight);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有截面高度参数",L"GDMPLab",L"2024-03-30");
        bOK = GetInstanceHorizontalLength(pInstance, beamLength);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有长度参数",L"GDMPLab",L"2024-03-30");

        if (ZPositionType == BeamZPositioningType::Top)
        {
            value = positionLevel + levelOffset +startOffset;
        }
        else if (ZPositionType == BeamZPositioningType::Bottom)
        {
            double validCosAngle = 0;
            if (!GetValidCosAngle(startOffset, endOffset, beamLength, validCosAngle))
            {
                return false;
            }
            value = positionLevel + levelOffset + startOffset + sectionHeight / validCosAngle;
        }
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetBasicBeamStartBottomElevation(const IInstance *pInstance, double &value)
{
    double startOffset = 0;
    double endOffset = 0;
    double levelOffset = 0;
    bool bStartEndOffsetExist = GetInstanceStartEndOffset(pInstance, startOffset, endOffset);
    bool bLevelOffsetExist = GetInstanceTopOffset(pInstance, levelOffset);

    if (bStartEndOffsetExist &&
        bLevelOffsetExist &&
        !MathUtils::IsEqual(startOffset - endOffset, 0, Constants::LENGTH_EPS))
    {
        BeamZPositioningType ZPositionType;
        double positionLevel = 0;
        double sectionHeight = 0;
        double beamLength = 0;

        bool bOK = GetBeamZPositionLineType(pInstance, ZPositionType);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有定位线位置参数",L"GDMPLab",L"2024-03-30");
        bOK = GetInstanceAssociatedLevelValue(pInstance, positionLevel);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有关联标高参数",L"GDMPLab",L"2024-03-30");
        bOK = GetBasicBeamSectionHeight(pInstance, sectionHeight);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有截面高度参数",L"GDMPLab",L"2024-03-30");
        bOK = GetInstanceHorizontalLength(pInstance, beamLength);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有长度参数",L"GDMPLab",L"2024-03-30");

        if (ZPositionType == BeamZPositioningType::Top)
        {
            double validCosAngle = 0;
            if (!GetValidCosAngle(startOffset, endOffset, beamLength, validCosAngle))
            {
                return false;
            }
            value = positionLevel + levelOffset + startOffset - sectionHeight / validCosAngle;
        }
        else if (ZPositionType == BeamZPositioningType::Bottom)
        {
            value = positionLevel + levelOffset + startOffset;
        }
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetBasicBeamEndTopElevation(const IInstance *pInstance, double &value)
{
    double startOffset = 0;
    double endOffset = 0;
    double levelOffset = 0;
    bool bStartEndOffsetExist = GetInstanceStartEndOffset(pInstance, startOffset, endOffset);
    bool bLevelOffsetExist = GetInstanceTopOffset(pInstance, levelOffset);

    if (bStartEndOffsetExist &&
        bLevelOffsetExist &&
        !MathUtils::IsEqual(startOffset - endOffset, 0, Constants::LENGTH_EPS))
    {
        BeamZPositioningType ZPositionType;
        double positionLevel = 0;
        double sectionHeight = 0;
        double beamLength = 0;

        bool bOK = GetBeamZPositionLineType(pInstance, ZPositionType);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有定位线位置参数",L"GDMPLab",L"2024-03-30");
        bOK = GetInstanceAssociatedLevelValue(pInstance, positionLevel);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有关联标高参数",L"GDMPLab",L"2024-03-30");
        bOK = GetBasicBeamSectionHeight(pInstance, sectionHeight);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有截面高度参数",L"GDMPLab",L"2024-03-30");
        bOK = GetInstanceHorizontalLength(pInstance, beamLength);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有长度参数",L"GDMPLab",L"2024-03-30");

        if (ZPositionType == BeamZPositioningType::Top)
        {
            value = positionLevel + levelOffset +endOffset;
        }
        else if (ZPositionType == BeamZPositioningType::Bottom)
        {
            double validCosAngle = 0;
            if (!GetValidCosAngle(startOffset, endOffset, beamLength, validCosAngle))
            {
                return false;
            }
            value = positionLevel + levelOffset + endOffset + sectionHeight / validCosAngle;
        }
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetBasicBeamEndBottomElevation(const IInstance *pInstance, double &value)
{
    double startOffset = 0;
    double endOffset = 0;
    double levelOffset = 0;
    bool bStartEndOffsetExist = GetInstanceStartEndOffset(pInstance, startOffset, endOffset);
    bool bLevelOffsetExist = GetInstanceTopOffset(pInstance, levelOffset);

    if (bStartEndOffsetExist &&
        bLevelOffsetExist &&
        !MathUtils::IsEqual(startOffset - endOffset, 0, Constants::LENGTH_EPS))
    {
        BeamZPositioningType ZPositionType;
        double positionLevel = 0;
        double sectionHeight = 0;
        double beamLength = 0;

        bool bOK = GetBeamZPositionLineType(pInstance, ZPositionType);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有定位线位置参数",L"GDMPLab",L"2024-03-30");
        bOK = GetInstanceAssociatedLevelValue(pInstance, positionLevel);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有关联标高参数",L"GDMPLab",L"2024-03-30");
        bOK = GetBasicBeamSectionHeight(pInstance, sectionHeight);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有截面高度参数",L"GDMPLab",L"2024-03-30");
        bOK = GetInstanceHorizontalLength(pInstance, beamLength);
        DBG_WARN_AND_RETURN_UNLESS(bOK, false, L"没有长度参数",L"GDMPLab",L"2024-03-30");

        if (ZPositionType == BeamZPositioningType::Top)
        {
            double validCosAngle = 0;
            if (!GetValidCosAngle(startOffset, endOffset, beamLength, validCosAngle))
            {
                return false;
            }
            value = positionLevel + levelOffset + endOffset - sectionHeight / validCosAngle;
        }
        else if (ZPositionType == BeamZPositioningType::Bottom)
        {
            value = positionLevel + levelOffset +endOffset;
        }
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetVariableSectionBeamTopElevation(const IInstance *pInstance, double &value)
{
    BeamZPositioningType ZPositionType;
    if (GetBeamZPositionLineType(pInstance, ZPositionType) && ZPositionType == BeamZPositioningType::Top)
    {
        double levelValue = 0;
        double levelOffset = 0;
        if(
            GetInstanceAssociatedLevelValue(pInstance,levelValue)&&
            GetInstanceTopOffset(pInstance, levelOffset))
        {
            value = levelValue + levelOffset;
            return true;
        }
    }
    return false;
}

bool StructureInstanceUtils::GetVariableSectionBeamStartBottomElevation(const IInstance *pInstance, double &value)
{
    double startHeight = 0;
    double endHeight = 0;
    double topElevation = 0;
    if (GetVariableSectionBeamTopElevation(pInstance,topElevation)&&
        GetVariableSectionBeamSectionHeight(pInstance,startHeight,endHeight))
    {
        value = topElevation - startHeight;
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetVariableSectionBeamEndBottomElevation(const IInstance *pInstance, double &value)
{
    double startHeight = 0;
    double endHeight = 0;
    double topElevation = 0;
    if (GetVariableSectionBeamTopElevation(pInstance, topElevation) &&
        GetVariableSectionBeamSectionHeight(pInstance, startHeight, endHeight))
    {
        value = topElevation - endHeight;
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetVariableSectionBeamBottomAngle(const IInstance *pInstance, double &value)
{
    double startHeight = 0;
    double endHeight = 0;
    double beamLength = 0;
    if (GetVariableSectionBeamSectionHeight(pInstance, startHeight, endHeight) &&
        GetInstanceHorizontalLength(pInstance, beamLength))
    {
        double cosAngle = 0;
        if (GetValidCosAngle(startHeight, endHeight, beamLength, cosAngle))
        {
            value = acos(cosAngle);
            return true;
        }
    }
    return false;
}

bool StructureInstanceUtils::GetBeamZPositionLineType(const IInstance *pInstance, gcmp::BeamZPositioningType &type)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IParameter> ZPositionParam = pInstance->GetElementParameters()->GetParameterByUid(PARAMETER_UID(BeamZPositioningTypeBuiltInParameter));
    DBG_WARN_AND_RETURN_UNLESS(IParameter::IsValidParameter(ZPositionParam), false, L"没有定位线位置参数",L"GDMPLab",L"2024-03-30");
    type = (BeamZPositioningType)ZPositionParam->GetValueAsInt();
    return true;
}

bool StructureInstanceUtils::GetInstanceAssociatedLevelValue(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    gcmp::ElementId planeId = gcmp::IElementPosition::GetAssociatedPlaneId(pInstance);
    const IDocument *pDoc = pInstance->GetDocument();
    DBG_WARN_AND_RETURN_UNLESS(pDoc, false, L"文档为空",L"GDMPLab",L"2024-03-30");
    double elevation(0.0);
    bool bOk = LevelUtils::GetLevelElevation(pDoc, planeId, elevation);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOk, L"GetLevelElevation失败",L"GDMPLab",L"2024-03-30");
    value = elevation;
    return true;
}

bool gcmp::StructureInstanceUtils::GetInstanceTopOffset(const IInstance *pInstance, double &topOffset)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IParameter> topOffSetParam = ELEMENT_PARAMETER(pInstance, TopOffsetBuiltInParameter);
    if (IParameter::IsValidParameter(topOffSetParam))
    {
        topOffset = topOffSetParam->GetValueAsDouble();
        return true;
    }
    return false;
}

bool gcmp::StructureInstanceUtils::GetWallCoreThickness(IDocument* pDoc, const ElementId& instanceTypeId, double& thickness)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    const IInstanceType* pInstanceType = quick_cast<const IInstanceType>(pDoc->GetElement(instanceTypeId));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");

    const IElementParameters* pParameterBehavior = pInstanceType->GetElementParameters();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pParameterBehavior, L"pParameterBehavior为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IParameter> paramThickness = pParameterBehavior->GetParameterByUid(PARAMETER_UID(CoreThicknessBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(IParameter::IsValidParameter(paramThickness), L"paramThickness无效",L"GDMPLab",L"2024-03-30");

    thickness = paramThickness->GetValueAsDouble();
    return true;
}

bool StructureInstanceUtils::GetInstanceStartEndOffset(const IInstance *pInstance, double &startOffset, double &endOffset)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IParameter> startOffsetParam = ELEMENT_PARAMETER(pInstance, StartOffsetBuiltInParameter);
    OwnerPtr<IParameter> endOffsetParam = ELEMENT_PARAMETER(pInstance, EndOffsetBuiltInParameter);
    if (IParameter::IsValidParameter(startOffsetParam) && IParameter::IsValidParameter(endOffsetParam))
    {
        startOffset = startOffsetParam->GetValueAsDouble();
        endOffset = endOffsetParam->GetValueAsDouble();
        return true;
    }
    return false;
}

bool StructureInstanceUtils::GetBasicBeamSectionHeight(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    UniIdentity sectionHeightParamUid = PARAMETER_UID(RectSectionHeightBuiltInParameter);
    bool bOK = GetInstanceFamilyTypeParamValueByParamUid(pInstance, value, sectionHeightParamUid);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOK, L"basicBeamSectionHeight为空",L"GDMPLab",L"2024-03-30");
    return true;

}

bool StructureInstanceUtils::GetVariableSectionBeamSectionHeight(const IInstance *pInstance, double &startHeight, double &endHeight)
{
    UniIdentity varBeamStartSectionHeightParamUid = PARAMETER_UID(RectSectionStartHeightBuiltInParameter);
    UniIdentity varBeamEndSectionHeightParamUid = PARAMETER_UID(RectSectionEndHeightBuiltInParameter);
    if (GetInstanceFamilyTypeParamValueByParamUid(pInstance, startHeight, varBeamStartSectionHeightParamUid)&&
        GetInstanceFamilyTypeParamValueByParamUid(pInstance, endHeight, varBeamEndSectionHeightParamUid))
    {
        return true;
    }
    DBG_WARN_AND_RETURN_FALSE_UNLESS(false, L"variableSectionBeamStartHeight或EndHeight为空",L"GDMPLab",L"2024-03-30");
}

bool StructureInstanceUtils::GetBasicBeamAngle(const IInstance* pInstance, double& angle)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    const IElementPosition* pPositionBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPositionBehavior, L"pPositionBehavior为空",L"GDMPLab",L"2024-03-30");
    const IPositionCurve2d* pPositionCurve2d = quick_cast<const IPositionCurve2d>(pPositionBehavior->GetPositionGeometry());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPositionCurve2d, L"pPositionCurve2d为空",L"GDMPLab",L"2024-03-30");
    const ICurve2d* pCurve2d = pPositionCurve2d->GetBaseCurve();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurve2d, L"pCurve2d为空",L"GDMPLab",L"2024-03-30");
    double length = pCurve2d->GetLength();
    bool bOk = !MathUtils::IsZero(length, Constants::LENGTH_EPS);
    if (!bOk)
        return false; // 拖拽夹点重合时

    const IPositionSingleAssociatedPlaneWithTwoOffsets* pPositionAssociatedPlaneWithTwoOffsets =
        quick_cast<const IPositionSingleAssociatedPlaneWithTwoOffsets>(pPositionBehavior->GetPositionAssociatedPlane());
    if (pPositionAssociatedPlaneWithTwoOffsets)
    {
        double startOffset = pPositionAssociatedPlaneWithTwoOffsets->GetStartOffset();
        double endOffset = pPositionAssociatedPlaneWithTwoOffsets->GetEndOffset();

        angle = fabs(atan((endOffset - startOffset) / length));
    }

    return true;
}

bool StructureInstanceUtils::IsLinearInstance(const IElement* pElement, bool& bLinear)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pElement, L"pElement为空",L"GDMPLab",L"2024-03-30");
    const IElementPosition* pPositionBehavior = pElement->GetElementPosition();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPositionBehavior, L"pPositionBehavior为空",L"GDMPLab",L"2024-03-30");
    const IPositionCurve2d* pPositionCurve2d = quick_cast<const IPositionCurve2d>(pPositionBehavior->GetPositionGeometry());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPositionCurve2d, L"pPositionCurve2d为空",L"GDMPLab",L"2024-03-30");

    const ILine2d* pLine2d = quick_cast<const ILine2d>(pPositionCurve2d->GetBaseCurve());
    if (pLine2d)
    {
        bLinear = true;
        return true;
    }
    return false;
}

bool StructureInstanceUtils::UpdateBeamCoordinateSystemParameter(IInstance* pInstance)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    const IElementPosition* pPositionBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPositionBehavior, L"pPositionBehavior为空",L"GDMPLab",L"2024-03-30");
    const IPositionSingleAssociatedPlaneWithTwoOffsets* pPositionAssociatedPlaneWithTwoOffsets =
        quick_cast<const IPositionSingleAssociatedPlaneWithTwoOffsets>(pPositionBehavior->GetPositionAssociatedPlane());
    // 非倾斜定位方式，无需更新CoordinateSystems
    if (!pPositionAssociatedPlaneWithTwoOffsets)
        return true;
    
    IElementParameters* pParamBehavior = pInstance->GetElementParameters();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pParamBehavior, L"pParamBehavior为空",L"GDMPLab",L"2024-03-30");

    // 设置CoordinateSystems为三维点
    OwnerPtr<IParameter> paramCoordinateSystem = pParamBehavior->GetParameterById(ELEMENT_PARAMETER_ID(pInstance, CoordinateSystemBuiltInParameter));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(IParameter::IsValidParameter(paramCoordinateSystem), L"paramCoordinateSystem无效",L"GDMPLab",L"2024-03-30");

    IParameterValueCurveByPoints* pPVCoordinateSystems = 
        quick_cast<IParameterValueCurveByPoints>(paramCoordinateSystem->GetParameterValueStorageFw());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPVCoordinateSystems, L"pPVCoordinateSystems为空",L"GDMPLab",L"2024-03-30");

    const IPositionCurve2d* pPositionCurve2d = quick_cast<const IPositionCurve2d>(pPositionBehavior->GetPositionGeometry());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pPositionCurve2d, L"pPositionCurve2d为空",L"GDMPLab",L"2024-03-30");

    if (const ILine2d* pLine2d = quick_cast<const ILine2d>(pPositionCurve2d->GetBaseCurve()))
    {
        bool bMirror = false;
        Matrix4d matTranfrom;
        OwnerPtr<IParameter> paramMirror = pParamBehavior->GetParameterByUid(PARAMETER_UID(InstanceMirrorSignBuiltInParameter));
        if (IParameter::IsValidParameter(paramMirror) && paramMirror->GetValueAsBool())
        {
            bMirror = true;
            matTranfrom.MakeMirror(Vector3d::Zero, Vector3d::UnitY);
        }

        OwnerPtr<ILine3d> opLine3d;
        {
            double baseOffset = pPositionAssociatedPlaneWithTwoOffsets->GetBasePlaneOffset();
            double startOffset = pPositionAssociatedPlaneWithTwoOffsets->GetStartOffset();
            double endOffset = pPositionAssociatedPlaneWithTwoOffsets->GetEndOffset();

            Vector3d lineStartPt(pLine2d->GetStartPoint().X(), pLine2d->GetStartPoint().Y(), baseOffset + startOffset);
            Vector3d lineEndPt(pLine2d->GetEndPoint().X(), pLine2d->GetEndPoint().Y(), baseOffset + endOffset);

            opLine3d = ILine3d::Create(lineStartPt, lineEndPt);
        }

        if (bMirror)
        {
            opLine3d->Transform(matTranfrom);
        }
        pPVCoordinateSystems->SetCoordinateSystemsByCurve3d(opLine3d.get());
    }
    else
    {
        // 圆弧暂不支持三维线
    }

    pParamBehavior->SetParameter(paramCoordinateSystem.get());
    return true;
}

bool StructureInstanceUtils::GetValidCosAngle(double startOffset, double endOffset, double beamLength, double &cosAngle)
{
    bool bLengthValid = !MathUtils::IsEqual(beamLength, 0, Constants::LENGTH_EPS);
    DBG_WARN_AND_RETURN_UNLESS(bLengthValid, false, L"梁长度不合法",L"GDMPLab",L"2024-03-30");
    //计算夹角（[0,90)度）的cos值
    double tanAngle = std::abs(startOffset - endOffset) / beamLength;
    double tmpCosAngle = 1.0 / std::sqrt(1 + tanAngle*tanAngle);
    bool bCosAngleValid = !MathUtils::IsEqual(tmpCosAngle, 0, Constants::DOUBLE_EPS);
    DBG_WARN_AND_RETURN_UNLESS(bCosAngleValid, false, L"梁角度不合法",L"GDMPLab",L"2024-03-30");
    cosAngle = tmpCosAngle;
    return true;
}

bool StructureInstanceUtils::GetStripFoundationTopElevation(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    double levelValue = 0;
    double topOffset = 0;
    double thickness = 0;
    StripFoundationZPositioningType Ztype;

    if (GetInstanceAssociatedLevelValue(pInstance, levelValue) &&
        GetInstanceTopOffset(pInstance, topOffset) &&
        GetStripFoundationThickness(pInstance, thickness) &&
        GetStripFoundationZPositioningType(pInstance, Ztype))
    {
        if (StripFoundationZPositioningType::Top == Ztype)
        {
            value = levelValue + topOffset;
            return true;
        }
        else if (StripFoundationZPositioningType::Bottom == Ztype)
        {
            value = levelValue + topOffset + thickness;
            return true;
        }
    }
    return false;
}

bool StructureInstanceUtils::GetStripFoundationBottomElevation(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    double topElevation = 0;
    double thickness = 0;
    if (GetStripFoundationTopElevation(pInstance, topElevation) &&
        GetStripFoundationThickness(pInstance, thickness))
    {
        value = topElevation - thickness;
        return true;
    }
    return false;
}


bool gcmp::StructureInstanceUtils::GetStripFoundationZPositioningType(const IInstance *pInstance, StripFoundationZPositioningType &type)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IParameter> ZPositionParam = pInstance->GetElementParameters()->GetParameterByUid(PARAMETER_UID(StripFoundationZPositioningTypeBuiltInParameter));
    DBG_WARN_AND_RETURN_UNLESS(IParameter::IsValidParameter(ZPositionParam), false, L"没有定位线位置参数",L"GDMPLab",L"2024-03-30");
    type = (StripFoundationZPositioningType)ZPositionParam->GetValueAsInt();
    return true;
}

bool gcmp::StructureInstanceUtils::GetStripFoundationThickness(const IInstance *pInstance, double &value)
{
    DBG_WARN_AND_RETURN_UNLESS(pInstance, false, L"构件为空",L"GDMPLab",L"2024-03-30");
    UniIdentity thicknessParamUid = PARAMETER_UID(RectSectionHeightBuiltInParameter);
    bool bOK = GetInstanceFamilyTypeParamValueByParamUid(pInstance, value, thicknessParamUid);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(bOK, L"raftFoundationThickness为空",L"GDMPLab",L"2024-03-30");
    return true;
}

//墙洞有效性检测：直墙（含变截面）/弧墙（可兼容变截面）
bool StructureInstanceUtils::ValidateStructureInstanceHole(const IInstance* pHostInstance, const IInstance* pHole)
{
    //洞口的CutterGrep与墙的BaseGrep相交
    const IBaseGraphicsElementShapeComponent* pBaseGraphicsElementShapeComponent = pHostInstance->GetBaseGraphicsElementShapeComponent();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pBaseGraphicsElementShapeComponent, L"pBaseGraphicsElementShapeComponent为空",L"GDMPLab",L"2024-03-30");

    const IGraphicsElementShape* wallBaseGrep = pBaseGraphicsElementShapeComponent->GetBaseGraphicsElementShape();

    OwnerPtr<IGraphicsElementShape> opClonedCutterGRep = nullptr;
    const IGeometryRelationshipComponent* pGeometryRepCpt = pHole->GetGeometryRelationshipComponent();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pGeometryRepCpt != nullptr, L"无效的指针",L"GDMPLab",L"2024-03-30");
    const IOpeningGraphicsElementShapeComponent* pCutterGRepComponent = pGeometryRepCpt->GetOpeningGraphicsElementShapeComponent();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCutterGRepComponent != nullptr, L"无效的指针",L"GDMPLab",L"2024-03-30");
    const IGraphicsElementShape* pCutterGRep = pCutterGRepComponent->GetOpeningGraphicsElementShape();

    if (!pCutterGRep)
        return true;

    opClonedCutterGRep = TransferOwnershipCast<IGraphicsElementShape>(pCutterGRep->Clone());
    const IElementPosition *posBehavior = pHole->GetElementPosition();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(posBehavior, L"无效的指针posBehavior",L"GDMPLab",L"2024-03-30");
    Matrix4d instanceTrans = posBehavior->ComputeLocalToWorldCoordinateSystemTransformMatrix();
    if (!instanceTrans.IsIdentity())
        opClonedCutterGRep->Transform(instanceTrans);

    BodiesPositionTypes positionType = GraphicsNodeUtils::GetBodiesPositionType(pHostInstance->GetDocument(), wallBaseGrep, opClonedCutterGRep.get());
    if (positionType != BodiesPositionTypes::Separation)
    {
        return true;
    }
    return false;
}

